﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Configuration;
using System.Configuration;
using System.Web.Management;
using System.Reflection;
using System.IO;
using System.Xml;
using Blackbaud.AppFx.XmlTypes;
using Blackbaud.AppFx.XmlTypes.DataForms;
using Blackbaud.AppFx.WebAPI.ServiceProxy;

namespace BBECServiceBusAdapter
{
    public class Helper
    {
        #region Defaults
        public const string DefaultMessageResponse = "Message Received";
        public const string Namespace = "http://blackbaud.com/BBECServiceBusAdapter";
        #endregion

        #region Miscellaneous objects

        public enum ErrorLevel
        {
            Error = 1,
            Warning = 2,
            Information = 4,
            Unknown = 16
        }

        public class ErrorDetailInfo
        {
            public int errorCode = 0;
            public string errorDescription = "";
            public ErrorLevel errorLevel = ErrorLevel.Information;
        }

        #endregion

        #region Configuration Helper
        public class Config
        {            
            public static string AppFxServiceUrl()
            {
                return ConfigurationManager.AppSettings["appFxServiceUrl"].ToString();
            }

            public static string DatabaseName()
            {
                return ConfigurationManager.AppSettings["databaseName"].ToString();
            }

            public static string ApplicationName(string callerID)
            {
                return ConfigurationManager.AppSettings["baseApplicationName"].ToString() + " (" + (string.IsNullOrEmpty(callerID) ? "[unspecified caller]" : callerID) + ")";
            }



            public static string CrmUserName()
            {
                return ConfigurationManager.AppSettings["CrmUserName"].ToString();
            }
            public static string CrmPassword()
            {
                return ConfigurationManager.AppSettings["CrmPassword"].ToString();
            }
            public static string CrmDomainName()
            {
                return ConfigurationManager.AppSettings["CrmDomainName"].ToString();
            }
            public static string CrmDomainNameAndUserName()
            {
                return CrmDomainName() + "\\" + CrmUserName(); 
            }



            public static string SecurityGroup(string operationName)
            {
                return ConfigurationManager.AppSettings["securityGroup_" + operationName].ToString();
            }

            public static LoggingLevelOption LoggingLevel()
            {
                string appSettingLoggingLevel = ConfigurationManager.AppSettings["loggingLevel"].ToString();
                switch (appSettingLoggingLevel)
                {
                    case "None":
                        {
                            return LoggingLevelOption.None;
                        }
                    case "Error":
                        {
                            return LoggingLevelOption.Error;
                        }
                    case "Warning":
                        {
                            return LoggingLevelOption.Warning;
                        }
                    case "Verbose":
                        {
                            return LoggingLevelOption.Verbose;
                        }
                    default:
                        {
                            return LoggingLevelOption.Error;
                        }
                }
            }

            public enum LoggingLevelOption
            {
                None,
                Error,
                Warning,
                Verbose
            }
        }
        #endregion

        #region Web Health Event
        public static void RaiseWebHealthEvent(string msg, object source)
        {
            ServiceAuthWebHealthEvent evt = new ServiceAuthWebHealthEvent(msg, source);
            System.Web.Management.WebBaseEvent.Raise(evt);
        }

        private class ServiceAuthWebHealthEvent : System.Web.Management.WebBaseEvent
        {
            public const int SERVICEAUTH_EVENT_BASECODE = WebEventCodes.WebExtendedBase + 2400000;
            public ServiceAuthWebHealthEvent(string msg, object source)
                : base(msg, source, SERVICEAUTH_EVENT_BASECODE)
            {
            }
        }
        #endregion

        #region Error Codes

        public static string GetErrorCodes()
        {
            try
            {
                using (Stream stream = Assembly.GetExecutingAssembly().GetManifestResourceStream("BBECServiceBusAdapter.Error_Codes.ErrorCodes.xml"))
                {
                    using (StreamReader sr = new StreamReader(stream))
                    {
                        return sr.ReadToEnd();
                    }
                }
            }
            catch 
            {
                return "No error codes defined";
            }
        }

        public static string GetErrorCodeDescription(int errorCode)
        {
            using (Stream stream = Assembly.GetExecutingAssembly().GetManifestResourceStream("BBECServiceBusAdapter.Error_Codes.ErrorCodes.xml"))
            {
                using (StreamReader sr = new StreamReader(stream))
                {
                    XmlDocument errorCodesXml = new XmlDocument();
                    errorCodesXml.Load(sr);

                    XmlNamespaceManager nsm = new XmlNamespaceManager(errorCodesXml.NameTable);
                    nsm.AddNamespace("sba", "urn:BBECServiceBusAdapter");
                    XmlNodeList errorCodeNodes = errorCodesXml.SelectNodes("sba:ErrorCodes/sba:ErrorCode", nsm);

                    foreach(XmlNode errorCodeNode in errorCodeNodes)
                    {
                        if (errorCodeNode.Attributes["Code"].Value == errorCode.ToString())
                        {
                            return errorCodeNode.Attributes["Description"].Value;
                        }
                    }

                    // if we get here nothing was found
                    return "[NO DESCRIPTION FOUND FOR ERROR CODE " + errorCode + "]";
                }
            }
        }

        public static string GetErrorCodeLevel(int errorCode)
        {
            using (Stream stream = Assembly.GetExecutingAssembly().GetManifestResourceStream("BBECServiceBusAdapter.Error_Codes.ErrorCodes.xml"))
            {
                using (StreamReader sr = new StreamReader(stream))
                {
                    XmlDocument errorCodesXml = new XmlDocument();
                    errorCodesXml.Load(sr);

                    XmlNamespaceManager nsm = new XmlNamespaceManager(errorCodesXml.NameTable);
                    nsm.AddNamespace("sba", "urn:BBECServiceBusAdapter");
                    XmlNodeList errorCodeNodes = errorCodesXml.SelectNodes("sba:ErrorCodes/sba:ErrorCode", nsm);

                    foreach (XmlNode errorCodeNode in errorCodeNodes)
                    {
                        if (errorCodeNode.Attributes["Code"].Value == errorCode.ToString())
                        {
                            return errorCodeNode.Attributes["Level"].Value;
                        }
                    }

                    // if we get here nothing was found
                    return "";
                }
            }
        }

        #endregion

#region Logging

        public static void CreateServiceBusAdapterLogEntry(Helper.ErrorLevel entryType, Guid workflowInstanceID, string details)
        {
            // initialize service
            AppFxWebService bbecService = new AppFxWebService();
            bbecService.Url = Helper.Config.AppFxServiceUrl();
            bbecService.UseDefaultCredentials = true;

            // initialize data form save request
            DataFormSaveRequest req = new DataFormSaveRequest();
            req.FormID = new Guid("aeeb34ef-9228-4593-bbcb-11367f9f8e80");
            ClientAppInfoHeader header = new ClientAppInfoHeader();
            header.ClientAppName = Helper.Config.ApplicationName("Service Bus Logger");
            header.REDatabaseToUse = Helper.Config.DatabaseName();
            req.ClientAppInfo = header;

            // set request properties
            DataFormItem dfi = new DataFormItem();
            dfi.SetValueIfNotNull("SERVERNAME", Environment.MachineName);
            dfi.SetValueIfNotNull("CORRELATIONID", workflowInstanceID);
            dfi.SetValueIfNotNull("ENTRYTYPECODE", (int)entryType);
            dfi.SetValueIfNotNull("DETAILS", details);
            req.DataFormItem = dfi;

            DataFormSaveReply reply = bbecService.DataFormSave(req);
        }




        public static Boolean IsValidGuid(String s) {
            Guid value;
            try {
                value = new Guid(s);
                if (value == Guid.Empty) {
                    return false;
                }
                else {
                return true;
                }
            }
            catch (FormatException) {
                return false;
            }
        }


#endregion
    }
}